package com.walkline.util;

import net.rim.device.api.system.CoverageInfo;
import net.rim.device.api.system.IDENInfo;
import net.rim.device.api.system.RadioInfo;
import net.rim.device.api.util.CharacterUtilities;

public class WirelessStatus 
{
	// Constants copied to allow building in 4.2.1 and for consistency
	private static final int EDGE = RadioInfo.NETWORK_SERVICE_EDGE;
	private static final int UMTS = RadioInfo.NETWORK_SERVICE_UMTS;
	private static final int EVDO = RadioInfo.NETWORK_SERVICE_EVDO_REV0;
	private static final int EVDO_REVA = 131072;
	private static final int EVDO_REV0 = 65536;
	private static final int COVERAGE_BIS_B = 0x04;

	// Arrays of Coverage Status descriptors
	private static String[] CDMA = { "", "D", "D", "1x", "1X", "1xev", "1XEV", "3G", "3G\uF8EB" };
	private static String[] GSM = { "", "gsm", "GSM", "gprs", "GPRS", "edge", "EDGE", "3G", "3G\uF8EB", "3g", "3G\uF8EB" };
	private static String[] IDEN = { "", "NXTL", "MIKE" };
	private static final int CDMA_VOICE = 2;
	//private static final int CDMA_1x = 3;
	private static final int CDMA_1X = 4;
	//private static final int CDMA_1xev = 5;
	private static final int CDMA_1XEV = 6;
	//private static final int CDMA_3G = 7;
	private static final int CDMA_3GBB = 8;
	//private static final int GPP_gsm = 1;
	private static final int GPP_GSM = 2;
	//private static final int GPP_gprs = 3;
	private static final int GPP_GPRS = 4;
	//private static final int GPP_edge = 5;
	private static final int GPP_EDGE = 6;
	//private static final int GPP_3G = 7;
	private static final int GPP_3GBB = 8;
	//private static final int GPP_3g = 9;
	private static final int GPP_3GEDGEBB = 10;
	private static final int IDEN_NXTL = 1;
	private static final int IDEN_MIKE = 2;
	private static boolean use3GForCDMA;
	//private static boolean BB7 = false;
		
	public String getWirelessDescriptor() {
		if (RadioInfo.getState() == RadioInfo.STATE_ON)
		{
			if ((RadioInfo.getNetworkService() & RadioInfo.NETWORK_SERVICE_EMERGENCY_ONLY) > 0) {
				return GSM[0];
			}

			int wafs = RadioInfo.getActiveWAFs();
			int service = RadioInfo.getNetworkService();

			String[] descriptors = GSM;
			int descriptorIndex = 0;

			if ((wafs & RadioInfo.WAF_3GPP) > 0)
			{
				descriptors = GSM;
				if ((service & UMTS) > 0 && ((service & EDGE) > 0 || !hasData(service)))
				{
					descriptorIndex = GPP_3GEDGEBB;
				} else if ((service & UMTS) > 0)
				{
					descriptorIndex = GPP_3GBB;
				} else if ((service & EDGE) > 0)
				{
					descriptorIndex = GPP_EDGE;
				} else if (hasData(service))
				{
					descriptorIndex = GPP_GPRS;
				} else if (hasVoice(service))
				{
					descriptorIndex = GPP_GSM;
				}
			} else if ((wafs & RadioInfo.WAF_CDMA) > 0)
			{
				descriptors = CDMA;
				if ((service & EVDO_REV0) > 0 || (service & EVDO_REVA) > 0 || (service & EVDO) > 0)
				{
					if (use3GForCDMA)
					{
						descriptorIndex = CDMA_3GBB;
					} else {
						descriptorIndex = CDMA_1XEV;
					}
				} else if (hasData(service))
				{
					descriptorIndex = CDMA_1X;
				} else if (hasVoice(service))
				{
					descriptorIndex = CDMA_VOICE;
				}
			} else if ((wafs & RadioInfo.WAF_IDEN) > 0)
			{
				StringBuffer descriptor;
				int mcc = IDENInfo.getHomeMCC();
				int ndc = IDENInfo.getHomeNDC();
				
				if (RadioInfo.getSignalLevel(RadioInfo.WAF_IDEN) == RadioInfo.LEVEL_NO_COVERAGE || (mcc == 0 && ndc == 0))
				{
					// no coverage
					return IDEN[0];
				}
				if (mcc == 0x0302 && ndc == 0x360)
				{
					// Mike network
					descriptor = new StringBuffer(IDEN[IDEN_MIKE]);
				} else {
					descriptor = new StringBuffer(IDEN[IDEN_NXTL]);
				}
				if (!hasVoice(service))
				{
					lowerCharacter(descriptor, 0);
				}
				if (!hasDirectConnect(service))
				{
					lowerCharacter(descriptor, 1);
				}
				if (!hasData(service))
				{
					lowerCharacter(descriptor, 2);
				}
				if (!isEmailAPNActive(RadioInfo.getActiveWAFs() & ~RadioInfo.WAF_WLAN))
				{
					lowerCharacter(descriptor, 3);
				}
				// done - doesn't follow the same format as GSM/CDMA
				return descriptor.toString();
			}
			if (!isEmailAPNActive(RadioInfo.getActiveWAFs() & ~RadioInfo.WAF_WLAN) && descriptorIndex > 0)
			{
				descriptorIndex--;
			}
			return descriptors[descriptorIndex];
		} else {
			return GSM[0];
		}
	}
	
	private boolean hasData(int service)
	{
		if ((service & RadioInfo.NETWORK_SERVICE_DATA) != 0) 
		{
			return true;
		}
		return false;
	}
	
	private boolean hasVoice(int service)
	{
		if ((service & RadioInfo.NETWORK_SERVICE_VOICE) != 0)
		{
			return true;
		}
		return false;
	}
	
	private void lowerCharacter(StringBuffer buffer, int index)
	{
		buffer.setCharAt(index, CharacterUtilities.toLowerCase(buffer.charAt(index)));
	}
	
	private boolean hasDirectConnect(int service) 
	{
		if ((service & RadioInfo.NETWORK_SERVICE_DIRECT_CONNECT) != 0) 
		{
			return true;
		}
		return false;
	}
	
	private boolean isEmailAPNActive(int wafs)
	{
		return CoverageInfo.isCoverageSufficient(CoverageInfo.COVERAGE_MDS, wafs, false)
				|| CoverageInfo.isCoverageSufficient(COVERAGE_BIS_B, wafs, false);
	}
}